package repo

import (
	"context"
	"forum/intr/adapter/driving/dao"
	"forum/intr/domain"
	"forum/intr/domain/cache"
	"forum/intr/domain/repo"
	"golang.org/x/sync/errgroup"
)

var _ repo.InteractiveRepository = &InteractiveRepositoryImp{}

type InteractiveRepositoryImp struct {
	interDao   dao.InteractiveDao
	interCache cache.InteractiveCache
}

func NewInteractiveRepositoryImp(interDao dao.InteractiveDao, interCache cache.InteractiveCache) *InteractiveRepositoryImp {
	return &InteractiveRepositoryImp{interDao: interDao, interCache: interCache}
}

func (i *InteractiveRepositoryImp) GetByIds(ctx context.Context, biz string, ids []int64) ([]domain.Interactive, error) {
	//TODO implement me
	panic("implement me")
}

func (i *InteractiveRepositoryImp) BatchReadCnt(ctx context.Context, bizs []string, ids []int64) error {
	return i.interDao.BatchIncrReadCnt(ctx, bizs, ids)
	//TODO cache
}

func (i *InteractiveRepositoryImp) IncrLike(ctx context.Context, biz string, id int64, uid int64) error {
	err := i.interDao.InsertLikeInfo(ctx, biz, id, uid)
	if err != nil {
		return err
	}
	return i.interCache.IncrLikeCntIfPresent(ctx, biz, id)
}

func (i *InteractiveRepositoryImp) DecrLike(ctx context.Context, biz string, id int64, uid int64) error {
	err := i.interDao.DeleteLikeInfo(ctx, biz, id, uid)
	if err != nil {
		return err
	}
	return i.interCache.DecrLikeCntIfPresent(ctx, biz, id)
}

func (i *InteractiveRepositoryImp) IncrCollect(ctx context.Context, biz string, id int64, uid int64) error {
	err := i.interDao.InsertCollectInfo(ctx, biz, id, uid)
	if err != nil {
		return err
	}
	return i.interCache.IncrCollectCntIfPresent(ctx, biz, id)
}

func (i *InteractiveRepositoryImp) DecrCollect(ctx context.Context, biz string, id int64, uid int64) error {
	err := i.interDao.DeleteCollectInfo(ctx, biz, id, uid)
	if err != nil {
		return err
	}
	return i.interCache.DecrCollectCntIfPresent(ctx, biz, id)
}

func (i *InteractiveRepositoryImp) GetById(ctx context.Context, biz string, id int64, uid int64) (domain.Interactive, error) {
	inter, err := i.interCache.Get(ctx, biz, id)
	if err == nil {
		return inter, err
	}
	//TODO 并发改造
	res, err := i.interDao.GetById(ctx, biz, id)
	var eg errgroup.Group
	eg.Go(func() error {
		liked, er := i.interDao.GetLiked(ctx, biz, id, uid)
		if er != nil {
			return er
		}
		res.Liked = liked
		return er
	})
	eg.Go(func() error {
		collected, er := i.interDao.GetCollected(ctx, biz, id, uid)
		if er != nil {
			return er
		}
		res.Collected = collected
		return er
	})

	if err != nil {
		return domain.Interactive{}, err
	}
	//回写缓存
	go func() {
		sErr := i.interCache.Set(ctx, biz, id, res)
		if sErr != nil {
			//log
		}
	}()
	return res, eg.Wait()
}

func (i *InteractiveRepositoryImp) IncrReadCnt(ctx context.Context, biz string, id int64) error {
	err := i.interDao.UpdateReadCnt(ctx, biz, id)
	if err != nil {
		return err
	}

	return i.interCache.IncrReadCnt(ctx, biz, id)
}
